<!-- RTC 11-15 -->
<template>
  <div class="video-chat">
    <!-- 视频双端显示 -->
    <div class="video_box">
      <div class="self_video" @click="switchPosition">
        <!-- <div class="text_tip">我：<span class="userId">{{ userId }}</span></div> -->
        <video ref="localVideo" autoplay muted="muted"></video>
      </div>
      <div class="remote_video" @click="switchPosition">
        <!-- <div class="text_tip">对方：<span class="userId">{{ oppositeUserId }}</span></div> -->
        <video ref="remoteVideo" muted="muted"></video>
      </div>
      <!-- 加入房间按钮 -->
      <div class="join_room_btn">
        <button @click="joinRoomHandle" v-if="!isJoin">加入通话</button>
        <button @click="exitRoomHandle(1)">退出通话</button>
      </div>
    </div>
    <!-- 日志打印 -->
    <!-- <div class="log_box">
      <pre>
          <div v-for="(item, index) of logData" :key="index">{{ item }}</div>
        </pre>
    </div> -->
  </div>
</template>
<script>
import axios from "axios";
import { useRouter } from "vue-router";

export default {
  props: {
    videoVisible: Boolean,
    receiveRoomId: String, // 接收一个字符串
    receiveUserId: String, // 接收一个数字
    receiveOppositeUserId: String, // 接收一个对象
    receiveVideoType: String
  },
  data() {
    return {
      localVideo: null,
      remoteVideo: null,
      isRoomEmpty: true, // 房间是否为空
      isJoin: false,
      videoType: "1", // 1: 请求通话， 2：正在通话， 3：退出通话
      roomStatusText: "点击‘加入房间’开始音视频聊天",
      logData: ["日志初始化..."],
      BaseUrl: "http://localhost:19090",
      candidateInfo: "",
      offerFlag: false,
      roomId: "",
      userId: "",
      oppositeUserId: "",
      localStream: null,
      peerConnection: null,
      signalingSocket: null,
      iceServers: [
        {
          urls: "stun:stun.l.google.com:19302"
        },
        {
          urls: "stun:自己的公网IP:3478"
        },
        {
          urls: "turn:自己的公网IP:3478",
          username: "maohe",
          credential: "maohe"
        }
      ]
    };
  },
  created() {
    // let urls = window.location.search.split("?")[1].split("&");
    
  },
  watch:{
    videoVisible(newVal){
      if (!newVal){
        console.log(newVal)
        this.signalingSocket.close()
      }
    }
  },

  mounted() {
    this.roomId = this.receiveRoomId;
    this.userId = this.receiveUserId;
    this.oppositeUserId = this.receiveOppositeUserId;
    this.videoType = this.receiveVideoType;
    if (this.videoType === "1") {
      this.joinRoomHandle();
    }
    this.localVideo = this.$refs.localVideo;
    this.remoteVideo = this.$refs.remoteVideo;
  },
  beforeDestroy(){
    console.log('结束')
    this.signalingSocket.close()
    this.localStream = null
    this.localVideo = null
  },
  methods: {
    joinRoomHandle() {
      this.roomStatusText = "等待对方加入房间...";
      this.isJoin = true;
      this.getVideoStream();
    },

    switchPosition() {
      if (!this.localVideo || !this.remoteVideo) return;
      let idx = Array.from(this.localVideo.parentElement.classList).findIndex(item => item === "remote_video") === -1 ? 1 : 2;
      this.localVideo.parentElement.classList = idx === 1?["remote_video"]:["self_video"]
    this.remoteVideo.parentElement.classList = idx === 2?["remote_video"]:["self_video"]

      this.wlog("已切换视频流");
    },

    getVideoStream() {
      const videoElement = document.createElement("video");
      videoElement.src = "/a.mp4";
      videoElement.loop = true;
      videoElement.muted = true;

      videoElement.onloadedmetadata = () => {
        const stream = videoElement.captureStream();
        this.localStream = stream;
        this.localVideo.srcObject = stream;
        this.wlog("获取本地流成功~");
        this.createPeerConnection();
      };

      videoElement.play();
    },

    initWebSocket() {
      this.wlog("开始连接websocket");
      this.signalingSocket = new WebSocket(`ws://localhost:19090/rtc?roomId=${this.roomId}&userId=${this.userId}`);

      this.signalingSocket.onopen = () => {
        this.wlog("WebSocket 已连接");
      };

      this.signalingSocket.onmessage = (event) => {
        this.handleSignalingMessage(event.data);
      };

      this.signalingSocket.onclose = (event) => {
        console.log('ws已关闭')
      };
    },

    handleSignalingMessage(message) {
      this.wlog("收到ws消息，开始解析...");
      this.wlog(message);
      let parseMsg = JSON.parse(message);
      this.wlog(`解析结果：${parseMsg}`);

      if (parseMsg.type === "join") {
        this.joinHandle(parseMsg.data);
      } else if (parseMsg.type === "offer") {
        this.wlog("收到发起端offer，开始解析...");
        this.offerHandle(parseMsg.data);
      } else if (parseMsg.type === "answer") {
        this.wlog("收到接收端的answer，开始解析...");
        this.answerHandle(parseMsg.data);
      } else if (parseMsg.type === "candidate") {
        this.wlog("收到远端candidate，开始解析...");
        this.candidateHandle(parseMsg.data);
      } else if (parseMsg.type === "leave") {
        console.log("关闭通话");
        this.exitRoomHandle(2)
      }
    },

    async candidateHandle(candidate) {
      this.peerConnection.addIceCandidate(new RTCIceCandidate(candidate));
      this.wlog("+++++++ 本端candidate设置完毕 ++++++++");
    },

    async answerHandle(answer) {
      this.wlog("将answer设置为远端信息");
      this.peerConnection.setRemoteDescription(new RTCSessionDescription(answer));
    },

    async offerHandle(offer) {
      this.wlog("将发起端的offer设置为远端媒体信息");
      await this.peerConnection.setRemoteDescription(new RTCSessionDescription(offer));
      this.wlog("创建Answer 并设置到本地");
      let answer = await this.peerConnection.createAnswer();
      await this.peerConnection.setLocalDescription(answer);

      this.wlog("发送answer给发起端");
      let paramObj = {
        userId: this.oppositeUserId,
        type: "answer",
        data: JSON.stringify(answer)
      };

      this.signalingSocket.send(JSON.stringify(paramObj));
    },

    joinHandle(userIds) {
      if (userIds.length === 1 && userIds[0] === this.userId) {
        this.wlog("标识为发起端，等待对方加入房间...");
        this.isRoomEmpty = true;
        this.offerFlag = true;
      } else if (userIds.length > 1) {
        this.wlog("对方已连接...");
        this.isRoomEmpty = false;

        for (let id of userIds) {
          if (id !== this.userId) {
            this.oppositeUserId = id;
          }
        }

        this.wlog(`对端ID: ${this.oppositeUserId}`);
        this.swapVideoInfo();
      }
    },

    async swapVideoInfo() {
      this.wlog("开始交换Sdp和Candidate...");
      if (this.offerFlag) {
        this.wlog("发起端创建offer");
        let offer = await this.peerConnection.createOffer();
        await this.peerConnection.setLocalDescription(offer);
        this.wlog("发启端设置SDP-offer到本地");

        let paramObj = {
          userId: this.oppositeUserId,
          type: "offer",
          data: JSON.stringify(offer)
        };

        this.wlog(`构造offer信息发送给远端：${paramObj}`);
        this.signalingSocket.send(JSON.stringify(paramObj));
      }
    },

    async sendCandidate(candidate) {
      let paramObj = {
        userId: this.oppositeUserId,
        type: "candidate",
        data: JSON.stringify(candidate)
      };

      this.wlog(`构造candidate信息发送给远端：${paramObj}`);
      this.signalingSocket.send(JSON.stringify(paramObj));
    },

    createPeerConnection() {
      let that = this
      this.wlog("开始创建PC对象...");
      this.peerConnection = new RTCPeerConnection(that.iceServers);
      this.initWebSocket();
      this.localStream.getTracks().forEach((track) => {
							this.peerConnection.addTrack(track, that.localStream);
						});
      this.peerConnection.onicecandidate = (event) => {
        if (event.candidate) {
          this.candidateInfo = event.candidate;
          this.wlog("candidate信息变化...");
          setTimeout(() => {
            this.sendCandidate(event.candidate);
          }, 150);
        }
      };

      this.peerConnection.ontrack = (event) => {
        this.$nextTick(() => {
          this.remoteVideo.srcObject = event.streams[0];
          this.remoteVideo.play();
        });
      };
    },

    wlog(text) {
      this.logData.unshift(text);
    },
    // 1:主动   2: 被动
    exitRoomHandle(action){
      this.$emit('exit', action)
    }
  }
};
</script>

<style scoped>
.video-chat {
  width: 96%;
  height: 90%;
  padding: 10px;
}
video {
  width: 100%;
  height: 100%;
  object-fit: cover; /* 保持比例，填满容器，可能会裁剪部分 */
}


.remote_video {
  margin-left: 20px;
  position: absolute;
  width: 100px;
  height: 100px;
  top: 0;
  right: 10px;
  background-color: #f1f1f1;
  video {
    width: 100%;
    height: 100%;
  }
}

.self_video {
  width: 100%;
  height: 100%;
  background-color: #e1e1e1;
  video {
    width: 100%;
    height: 100%;
    max-height: 420px;
  }
}

.video_box {
  position: relative;
  width: 100%;
  height: 100%;
}

.join_room_btn{
  position: absolute;
  top: 70%;
  left: 46%;
}

.join_room_btn {
  button{
    border: none;
    height: 30px;
    width: 80px;
    border-radius: 10px;
    color: white;
    margin-top: 10px;
    cursor: pointer;
    font-size: 13px;
  }
  button:first-child {
    background-color: rgb(119 178 63);
    margin-right: 10px;
  }
  button:last-child {
    background-color: rgb(204, 61, 35);
    margin-right: 10px;
  }
}

.text_tip {
  font-size: 13px;
  color: #484848;
  padding: 6px;
}

pre {
  width: 600px;
  height: 300px;
  background-color: #d4d4d4;
  border-radius: 10px;
  padding: 10px;
  overflow-y: auto;
}

pre div {
  padding: 4px 0px;
  font-size: 15px;
}

.userId{
  color: #3669ad;
}

.video-chat p{
  font-weight: 600;
  color: #b24242;
}
</style>